package demo.hadoop.tsdb;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.lang.StringUtils;

/**
 * <li>Only the following characters are allowed: a to z, A to Z, 0 to 9, -, _,
 * ., / or Unicode letters (as per the specification)
 */
public class TSDBEncodeUtil implements Serializable {

    /**
     *
     */
    private static final long serialVersionUID = -3112105758178505546L;
    private static Map<Character, String> encodeMap = new HashMap<Character, String>();
    private static Map<Character, String> specialMap = new HashMap<Character, String>();
    static {
        encodeMap.put('@', "//A//");
        encodeMap.put(':', "//B//");
        encodeMap.put(' ', "//C//");
        encodeMap.put(',', "//D//");
        encodeMap.put('{', "//E//");
        encodeMap.put('}', "//F//");
        encodeMap.put('%', "//G//");
        encodeMap.put('$', "//H//");
        encodeMap.put('(', "//I//");
        encodeMap.put(')', "//J//");
        encodeMap.put('[', "//K//");
        encodeMap.put(']', "//L//");
        encodeMap.put('<', "//M//");
        encodeMap.put('>', "//N//");

        encodeMap.put('?', "//P//");
        encodeMap.put('^', "//Q//");
        encodeMap.put('\\', "//R//");
        encodeMap.put('+', "//S//");
        encodeMap.put('`', "//T//");
        encodeMap.put('\'', "//U//");
        encodeMap.put('=', "//V//");
        encodeMap.put(';', "//W//");
        encodeMap.put('&', "//X//");
        encodeMap.put('!', "//Y//");
        encodeMap.put('"', "//Z//");
        encodeMap.put('#', "//z//");
        encodeMap.put('~', "//a//");

        specialMap.put('*', "//O//");
    }

    public static Map<Character, String> getEncodeMap() {
        Map<Character, String> map = new HashMap<Character, String>();
        map.putAll(encodeMap);
        map.putAll(specialMap);
        return map;
    }

    public static String encode(String s) {
        if (StringUtils.isBlank(s)) {
            return s;
        }
        if (isSpecial(s)) {
            s = doEncode(s, specialMap);
        }
        s = doEncode(s, encodeMap);
        return s;
    }

    private static boolean isSpecial(String s) {
        if (s.contains("*") && s.contains("/")) {
            return true;
        }
        return false;
    }

    private static String doEncode(String s, Map<Character, String> codeMap) {
        for (Character key : codeMap.keySet()) {
            s = StringUtils.replace(s, key + "", codeMap.get(key));
        }
        return s;
    }

    public static Map<String, String> encodeMap(Map<String, String> tags) {
        if (tags == null)
            return tags;
        Map<String, String> resultMap = new HashMap<String, String>();
        Iterator<Map.Entry<String, String>> iterator = tags.entrySet().iterator();

        while (iterator.hasNext()) {
            Map.Entry<String, String> entry = iterator.next();
            String newValue = entry.getValue();
            if (StringUtils.isNotBlank(newValue)) {
//                for (Character key : encodeMap.keySet()) {
//                    newValue = StringUtils.replace(newValue, String.valueOf(key), encodeMap.get(key));
//                }
                newValue = encode(newValue);
                resultMap.put(entry.getKey(), newValue);
            }
        }
        return resultMap;
    }

    private static String encodeLogIdentity(String logIdentity) {
        // stringToAscii
        StringBuffer sbu = new StringBuffer();
        char[] chars = logIdentity.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            if (i != chars.length - 1) {
                sbu.append((int) chars[i]).append("-");
            } else {
                sbu.append((int) chars[i]);
            }
        }
        return sbu.toString();
    }

    public static void main(String[] args) {
        String orignalString = "/srv/wap/app/GET (?-mix:^\\\\/([\\\\d]+)\\\\/sound\\\\/([\\\\d]+)$)/v2_=;&!\"#r.rb/halt_404'/=;&!\"#";
        validateString("", TSDBEncodeUtil.encode(orignalString));
        test(orignalString);
    }

    private static void test(String a) {
        System.out.println(String.format("原始字符串：%s", a));
        String s = TSDBEncodeUtil.encode(a);
        System.out.println(String.format("编码字符串：%s", s));
        System.out.println(String.format("解码字符串：%s", TSDBDecodeUtil.decode(s)));
    }

    private static void validateString(final String what, final String s) {
        if (s == null) {
            throw new IllegalArgumentException("Invalid " + what + ": null");
        }
        final int n = s.length();
        for (int i = 0; i < n; i++) {
            final char c = s.charAt(i);
            if (!(('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '-' || c == '_'
                    || c == '.' || c == '/' || Character.isLetter(c))) {
                System.out.println(String.format("illegal character:[%s]", c));
            }
        }
    }
}
